package com.alex.ip.holder.server.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alex.ip.holder.common.enums.ServerStatus;
import com.alex.ip.holder.common.vo.ClientVO;
import com.alex.ip.holder.server.properties.HolderProperties;
import com.alex.ip.holder.server.properties.HolderProperties.Client;
import com.alex.ip.holder.server.service.ClientService;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;

/**
 * @author Alex.Liu
 * @date: 2025-02-18 16:28
 * @since 1.0.0
 */
@Slf4j
public abstract class AbstractClientService implements ClientService, InitializingBean {

    @Resource
    private ScheduledExecutorService scheduledExecutorService;

    @Resource
    protected HolderProperties properties;

    /**
     * 獲取服務
     *
     * @return
     */
    protected abstract List<ClientVO> getClientList();

    protected abstract Boolean update(List<ClientVO> clients);

    /**
     * 健康檢查
     *
     * @return
     */
    private Boolean check() {
        Client config = properties.getClient();
        if (!config.isCheckEnabled()) {
            log.warn("服務健康檢查未開啟");
            return Boolean.FALSE;
        }
        List<ClientVO> clients = getClientList();
        if (CollUtil.isEmpty(clients)) {
            log.warn("暫無可用服務");
            return Boolean.FALSE;
        }
        clients.forEach(client -> {
            String url = client.toURL() + config.getCheckUri();
            HttpRequest request = HttpUtil.createRequest(config.getCheckMethod(), url);
            request.timeout(config.getCheckTimeout());
            try (HttpResponse response = request.execute()) {
                if (response.isOk()) {
                    client.setStatus(StrUtil.equals(response.body(), config.getSuccessResult()) ? ServerStatus.ONLINE : ServerStatus.UNREACHABLE);
                }
            } catch (Exception e) {
                client.setStatus(ServerStatus.OFFLINE);
                log.error("URL={} client={}", url, client, e);
            } finally {
                client.setLastUpdateTime(System.currentTimeMillis());
                if (log.isDebugEnabled()) {
                    log.debug("健康檢查完畢={}", client);
                }
            }
        });
        // 更新緩存
        return this.update(clients);
    }

    /**
     * 更新服務列表
     *
     * @param clients
     */


    /**
     * 啟動服務檢查線程
     *
     * @throws Exception
     */
    @Override
    public final void afterPropertiesSet() throws Exception {
        scheduledExecutorService.scheduleWithFixedDelay(this::check, 10, 30, TimeUnit.SECONDS);
    }
}
